package gameframe;

import client.ClientPlayer;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

/**
 * @author Hsu琛君珩
 * @ClassName:ChatPanel
 * @date 2023-12-21
 * @apiNote
 * @Version: v1.0
 */

/**
 * 聊天面板类。
 * 负责显示聊天信息、发送消息以及提供悔棋和认输的按钮。
 */
public class ChatPanel extends JPanel {
    private static ChatPanel instance; // 聊天面板的单例实例
    // 聊天面板中的组件
    private JTextPane chatPane; // 显示聊天内容的文本窗格
    private JTextPane inputPane; // 用户输入聊天内容的文本窗格
    private JScrollPane scrollPane; // 包含chatPane的滚动面板
    private JButton sendButton; // 发送消息的按钮
    private JButton regretButton; // 悔棋的按钮
    private JButton surrenderButton; // 认输的按钮

    /**
     * 获取ChatPanel的单例实例。
     * 如果实例不存在，则创建一个新实例。
     *
     * @return ChatPanel的单例实例
     */
    public static ChatPanel getInstance() {
        if (instance == null) {
            instance = new ChatPanel();
        }
        return instance;
    }

    /**
     * 构造方法，私有化以防止外部直接创建实例。
     * 初始化聊天面板的组件。
     */
    private ChatPanel() {
        initializeComponents();
        initActionListener();
    }

    /**
     * 初始化组件。
     * 创建并配置聊天面板的各个组件，包括聊天显示区域、输入区域和按钮。
     */
    private void initializeComponents() {
        this.setLayout(null); // 设置布局管理器为null，使用绝对定位
        this.setBounds(420, 0, 200, 420); // 设置面板大小和位置
        this.setBackground(new Color(147, 98, 31,255)); // 设置面板背景色
        // 初始化并设置聊天内容显示区域
        chatPane = new JTextPane();
        chatPane.setEditable(false); // 设置为不可编辑
        chatPane.setBounds(0,0,200,200);
        chatPane.setBackground(new Color(190, 115, 80,255)); // 设置背景色
        // 初始化并设置包含chatPane的滚动面板
        scrollPane = new JScrollPane(chatPane);
        scrollPane.setBounds(460, 20, 200, 200); // 设置大小和位置
        styleScrollPane(scrollPane); // 应用样式
        // 初始化并设置用户输入聊天内容的区域
        inputPane = new JTextPane();
        inputPane.setBounds(460, 220, 200, 100); // 设置大小和位置
        inputPane.setBackground(new Color(190, 115, 80,255)); // 设置背景色
        styleScrollPane(inputPane); // 应用样式
        // 初始化并设置发送消息的按钮
        sendButton = new JButton("发送");
        sendButton.setBounds(580,360,80,20); // 设置大小和位置
        styleButton(sendButton); // 应用样式
        // 初始化并设置悔棋的按钮
        regretButton = new JButton("悔棋");
        regretButton.setBounds(460,390,80,20); // 设置大小和位置
        styleButton(regretButton); // 应用样式
        // 初始化并设置认输的按钮
        surrenderButton = new JButton("认输");
        surrenderButton.setBounds(580,390,80,20); // 设置大小和位置
        styleButton(surrenderButton); // 应用样式
        // 将组件添加到面板中
        this.add(scrollPane);
        this.add(inputPane);
        this.add(sendButton);
        this.add(regretButton);
        this.add(surrenderButton);
    }

    /**
     * 初始化事件监听器。
     * 为输入框、发送、悔棋和认输按钮添加事件处理程序。
     */
    private void initActionListener() {
        // 添加输入框事件监听器
        inputPane.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                // 当用户按下回车键时发送消息
                if (e.getKeyChar() == KeyEvent.VK_ENTER) {
                    localUpdateText();
                }
            }
        });

        // 添加发送按钮事件监听器
        sendButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                // 发送消息
                localUpdateText();
            }
        });

        // 添加悔棋按钮事件监听器
        regretButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                // 处理悔棋请求
                handleRegret();
            }
        });

        // 添加认输按钮事件监听器
        surrenderButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                // 发送认输请求
                ClientPlayer.getInstance().surrender();
            }
        });
    }

    /**
     * 本地更新聊天信息。
     * 从用户输入框获取文本，发送到服务器，并更新聊天框以显示新的聊天信息。
     * 如果用户输入为空，则不会发送任何消息。
     * 发送成功后，清空输入框并确保新的消息在聊天框中可见。
     */
    private void localUpdateText() {
        // 获取输入框中的文本，并去除前后空白字符。
        String inputStr = inputPane.getText().trim();
        if (inputStr.isEmpty()) {
            // 如果输入内容为空，不执行任何操作。
            return;
        }
        // 清空输入框以准备下一次输入。
        inputPane.setText("");
        // 发送聊天信息到服务器。
        ClientPlayer.getInstance().sendChatMessage(inputStr);
        // 将发送的消息添加到聊天框中。
        String currentChatContent = chatPane.getText();
        StringBuilder builder = new StringBuilder();
        if (!currentChatContent.isEmpty()) {
            builder.append(currentChatContent).append("\n");
        }
        builder.append(ClientPlayer.getInstance().getUserName()).append(": ").append(inputStr);
        chatPane.setText(builder.toString());
        // 确保聊天框滚动到最新消息处。
        chatPane.setCaretPosition(chatPane.getDocument().getLength());
    }

    /**
     * 更新聊天面板的文本。
     * 用于将新的聊天信息显示在聊天面板上。
     * @param chatInfo 新的聊天信息。
     */
    public void updateText(String chatInfo) {
        // 直接更新聊天框的内容为最新的聊天信息。
        chatPane.setText(chatInfo);
    }

    /**
     * 处理悔棋按钮的点击事件。
     * 根据当前按钮的文本执行不同的操作：请求悔棋、开始复盘或显示下一步棋。
     */
    private void handleRegret() {
        String buttonText = regretButton.getText();
        if (buttonText.equals("悔棋")) {
            // 发送悔棋请求到服务器。
            ClientPlayer.getInstance().regretChess();
        } else if (buttonText.equals("复盘")) {
            // 开始复盘，改变按钮文本以提供下一步操作。
            regretButton.setText("下一步");
            ClientPlayer.getInstance().reShow();
        } else if (buttonText.equals("下一步")) {
            // 显示复盘的下一步棋。
            ClientPlayer.getInstance().reShow();
        }
    }

    /**
     * 初始化复盘操作。
     * 设置按钮文本为复盘开始状态，并准备棋盘复盘状态。
     */
    public void initRePlay() {
        regretButton.setText("复盘");
        ChessPanel.getInstance().initRePlay();
    }

    /**
     * 样式化滚动面板。
     * 为滚动面板设置复合边框，增加视觉层次和美观度。
     * @param scrollPane 需要样式化的滚动面板
     */
    private void styleScrollPane(JComponent scrollPane) {
        scrollPane.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createLineBorder(new Color(0, 0, 0), 2),
                BorderFactory.createLineBorder(new Color(128, 64, 0), 4)
        ));
    }

    /**
     * 样式化按钮。
     * 为按钮设置背景颜色和焦点绘制行为，确保按钮风格一致且美观。
     * @param button 需要样式化的按钮
     */
    private void styleButton(JButton button) {
        button.setBackground(new Color(192, 128, 64)); // 设置按钮背景色为淡棕色
        button.setFocusPainted(false); // 禁用绘制按钮获得焦点时的边框
    }

}
